//==================================================================
//  Copyright (C) 2006-2007  Davide Pasca
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//==================================================================
/// @file
///
///
/// 
/// @author Davide Pasca
/// 
//==================================================================

#include "stdafx.h"

#ifdef TARGET_D3D
#include "rend_shaders_d3d.h"
#include "rend_shaders_d3d_inl.h"

#elif defined(TARGET_OPENGL)

	#include "../pc_ogl/shaders/hexed/StdTypes.cg.h"
	#include "../pc_ogl/shaders/hexed/StdPrimPipePS.cg.h"
	#include "../pc_ogl/shaders/hexed/StdPrimPipeVS.cg.h"

	#pragma comment( lib, "cg.lib" )
	#pragma comment( lib, "cgGL.lib" )

#endif

#include "rend_device.h"

//==================================================================
using namespace PMath;
using std::string;


#if defined(TARGET_OPENGL)
//==================================================================
static void mycgErrorCheck( CGcontext ctx, const TCHAR *srcfnamep, int line )
{
	CGerror error = cgGetError();
	if ( error )
	{
		const char *errorString = cgGetErrorString(error);

		PDEBUG_PRINTF( _T("CG Error: %s [%s line %d]\n"), errorString, srcfnamep, line );
		if ( error == CG_COMPILER_ERROR )
		{
			PDEBUG_PRINTF( _T("Error Details: %s\n"), cgGetLastListing( ctx ) );
			PASSERT( 0 );
		}
	}
}

//==================================================================
#ifdef _DEBUG
	#define CGERRORCHECK(_CTX_)	mycgErrorCheck( _CTX_, __FILE__, __LINE__ )
#else
	#define CGERRORCHECK
#endif

#endif

//==================================================================
RendShaderManager::RendShaderManager() :
	_Std(this),
	_rdevicep(NULL),
	_context(0),
	_cur_vtx_shaderp(NULL),
	_cur_pix_shaderp(NULL),
	_vs_profile(CG_PROFILE_UNKNOWN),
	_ps_profile(CG_PROFILE_UNKNOWN)
{
	_cur_proj_mat.Identity();
}

//==================================================================
void RendShaderManager::myCgErrorHandler_s( CGcontext context, CGerror error, void *data )
{
	const TCHAR *errorString = PSYS::ANSIToTCHAR( cgGetErrorString(error) );
	PDEBUG_PRINTF( _T("%s\n"), errorString );
	delete [] errorString;

	if ( error == CG_COMPILER_ERROR )
	{
		PDEBUG_PRINTF( _T("Error Details: %s\n"), cgGetLastListing( context ) );
		PASSERT( 0 );
	}
}

//==================================================================
void RendShaderManager::Initialize( RendDevice *rdevicep, const TCHAR *datadirp )
{
	_rdevicep = rdevicep;

#if defined(TARGET_OPENGL)
	cgSetErrorHandler( myCgErrorHandler_s, this );

	_context = cgCreateContext();

//	cgGLSetManageTextureParameters( _context, CG_TRUE );

	// Initialize profiles and compiler options
	_vs_profile = cgGLGetLatestProfile( CG_GL_VERTEX );
	cgGLSetOptimalOptions( _vs_profile );

	_ps_profile = cgGLGetLatestProfile( CG_GL_FRAGMENT );
	cgGLSetOptimalOptions( _ps_profile );
#endif

	_Std.Initialize();
}

//==================================================================
RendShaderManager::~RendShaderManager(void)
{
	cgDestroyContext( _context );
}

//==================================================================
static void SetFrustum( Matrix44 &m, float l, float r, float b, float t, float n, float f )
{
float	rl, tb, fn;

	if ( (rl = r - l) == 0 || (tb = t - b) == 0 || (fn = f - n) == 0 )
		return;

	m._m11 = 2 * n / rl; m._m21 = 0;          m._m31 =  (r + l) / rl; m._m41 = 0; 
	m._m12 = 0;          m._m22 = 2 * n / tb; m._m32 =  (t + b) / tb; m._m42 = 0; 
	m._m13 = 0;          m._m23 = 0;          m._m33 = -(f + n) / fn; m._m43 = -2 * f * n / fn;
	m._m14 = 0;          m._m24 = 0;          m._m34 = -1;            m._m44 = 0; 
}

//==================================================================
void RendShaderManager::SetProjMatrix( const Matrix44 &proj_mat )
{
	_cur_proj_mat = proj_mat;

#if defined(TARGET_OPENGL)
	glMatrixMode( GL_PROJECTION );
	glLoadMatrixf( (float *)_cur_proj_mat._m );
	glMatrixMode( GL_MODELVIEW );

#endif
}

//==================================================================
// remember to call this AFTER SetProjMatrix()
void RendShaderManager::SetModelviewMatrix0( const Matrix44 &modelview_mat )
{
#ifdef TARGET_D3D

#elif defined(TARGET_OPENGL)
	glLoadMatrixf( (float *)modelview_mat._m );
#endif
}


//==================================================================
void RendShaderManager::PushMainMatrices()
{
	// $$$ !!! - _cur_proj_mat = proj_mat;
#if defined(TARGET_OPENGL)
	glMatrixMode( GL_PROJECTION );
	glPushMatrix();
	glMatrixMode( GL_MODELVIEW );
	glPushMatrix();

#endif
}

//==================================================================
void RendShaderManager::PopMainMatrices()
{
#if defined(TARGET_OPENGL)
	glMatrixMode( GL_PROJECTION );
	glPopMatrix();
	glMatrixMode( GL_MODELVIEW );
	glPopMatrix();

#endif
}

//==================================================================
void RendShaderManager::LoadMainMatrices( RendShader::Param proj_mat_param,
										  RendShader::Param modelview_mat_param )
{
#if defined(TARGET_OPENGL)
	cgGLSetStateMatrixParameter( proj_mat_param, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY );
	cgGLSetStateMatrixParameter( modelview_mat_param, CG_GL_MODELVIEW_MATRIX, CG_GL_MATRIX_IDENTITY );
#endif
}


//==================================================================
void RendShaderManager::SetMatrix44( RendShader::Param mat_param, const Matrix44 &mat )
{
#if defined(TARGET_OPENGL)
	cgGLSetMatrixParameterfc( mat_param, mat._m[0] );
#endif
}

/*
//==================================================================
void RendDeviceState::SetTexture( TextureBase *texturep )
{
	if ( _texturep == texturep )
		return;
	_texturep = texturep;
}
*/
//==================================================================
void RendShaderManager::Std::SetSHLightMatrices( const Matrix44 rgb_sh_light_obj_m[3],
											const Vector4 &os_light_dir )
{
#ifdef TARGET_D3D
	D3DDevice	*d3ddevp = _rdevicep->GetD3DDevice();
	d3ddevp->SetVertexShaderConstantF( _VSP_U_r_light_obj_m, (float *)rgb_sh_light_obj_m[0]._m, 4 );
	d3ddevp->SetVertexShaderConstantF( _VSP_U_g_light_obj_m, (float *)rgb_sh_light_obj_m[1]._m, 4 );
	d3ddevp->SetVertexShaderConstantF( _VSP_U_b_light_obj_m, (float *)rgb_sh_light_obj_m[2]._m, 4 );
	d3ddevp->SetVertexShaderConstantF( _VSP_U_light_pos, os_light_dir._v, 1 );
#elif defined(TARGET_OPENGL)
	cgGLSetMatrixParameterfr( _VSP_U_r_light_obj_m, (const float *)rgb_sh_light_obj_m[0]._m );
	cgGLSetMatrixParameterfr( _VSP_U_g_light_obj_m, (const float *)rgb_sh_light_obj_m[1]._m );
	cgGLSetMatrixParameterfr( _VSP_U_b_light_obj_m, (const float *)rgb_sh_light_obj_m[2]._m );
	cgGLSetParameter4fv( _VSP_U_light_pos, os_light_dir._v );
#endif
}

//==================================================================
///
//==================================================================
void RendShaderManager::Std::Initialize()
{
	RendShader		*base_vshaderp = NULL;

#if defined(TARGET_OPENGL)
	string	vs_source_str(	string( (const char *)_StdTypes_cg) + 
		string( (const char *)_StdPrimPipeVS_cg ) );
#endif

	for (int tex=0; tex < 2; ++tex)
	{
		for (int col=0; col < 2; ++col)
		{
			for (int nor=0; nor < 2; ++nor)
			{
				char	vsnamebuff[1024];

				MakeStdVSName_s( vsnamebuff, tex, col, nor );

				_std_vs_shaderp[tex][col][nor] = 
					_managerp->CreateVertexShaderFromSource( vs_source_str.c_str(), vsnamebuff );

				RendShader	*shaderp = _std_vs_shaderp[tex][col][nor];

				if NOT( base_vshaderp )
				{
					base_vshaderp = shaderp;

					_VSP_U_proj_obj_m	= shaderp->AddParamShared( "_proj_obj_m"		);
					_VSP_U_view_obj_m	= shaderp->AddParamShared( "_view_obj_m"		);
					_VSP_U_light_pos	= shaderp->AddParamShared( "_light_pos"		);
					_VSP_U_diffuse_col	= shaderp->AddParamShared( "_diffuse_col"	);
					_VSP_U_emissive_col	= shaderp->AddParamShared( "_emissive_col"	);
					_VSP_U_r_light_obj_m= shaderp->AddParamShared( "_r_light_obj_m"	);
					_VSP_U_g_light_obj_m= shaderp->AddParamShared( "_g_light_obj_m"	);
					_VSP_U_b_light_obj_m= shaderp->AddParamShared( "_b_light_obj_m"	);
					_VSP_U_fog_range	= shaderp->AddParamShared( "_fog_range"		);
				}
				else
				{
					shaderp->CloneParam( "_proj_obj_m"		, base_vshaderp );
					shaderp->CloneParam( "_view_obj_m"		, base_vshaderp );
					shaderp->CloneParam( "_light_pos"		, base_vshaderp );
					shaderp->CloneParam( "_diffuse_col"		, base_vshaderp );
					shaderp->CloneParam( "_emissive_col"	, base_vshaderp );
					shaderp->CloneParam( "_r_light_obj_m"	, base_vshaderp );
					shaderp->CloneParam( "_g_light_obj_m"	, base_vshaderp );
					shaderp->CloneParam( "_b_light_obj_m"	, base_vshaderp );
					shaderp->CloneParam( "_fog_range"		, base_vshaderp );
				}
			}
		}
	}

	RendShader	*base_pshaderp = NULL;

#if defined(TARGET_OPENGL)
	string	ps_source_str(	string( (const char *)_StdTypes_cg) +  string( (const char *)_StdPrimPipePS_cg ) );
#endif

	for (int tex=0; tex < 2; ++tex)
	{
		for (int nor=0; nor < 2; ++nor)
		{
			char	ps_entry_point[128];

			MakeStdPSName_s( ps_entry_point, tex, nor );

			_std_ps_shaderp[tex][nor] =
				_managerp->CreatePixelShaderFromSource( ps_source_str.c_str(), ps_entry_point );

			RendShader	*shaderp = _std_ps_shaderp[tex][nor];

			if NOT( base_pshaderp )
			{
				base_pshaderp = shaderp;

				_FSP_U_color_texmap[0] = shaderp->AddParam( "_color_texmap" );
				//_FSP_U_color_texmap		= shaderp->AddParamShared( "_color_texmap"		);
				_FSP_U_fog_col			= shaderp->AddParamShared( "_fog_col"			);
				_FSP_U_specular_col_pow	= shaderp->AddParamShared( "_specular_col_pow"	);
			}
			else
			{
				//shaderp->CloneParam( "_color_texmap"		, base_pshaderp );
				shaderp->CloneParam( "_fog_col"				, base_pshaderp );
				shaderp->CloneParam( "_specular_col_pow"	, base_pshaderp );
			}

			//if ( tex )
			//	_FSP_U_color_texmap[nor] = shaderp->AddParam( "_color_texmap" );
		}
	}
}

//==================================================================
void RendShaderManager::Std::SetBaseColor( const Vector4 &diffuse_col,
								const Vector3 &specular_col, float spec_pow,
								const Vector4 &emissive_col )
{
	Vector4	spec( specular_col*_global_specular_coe, spec_pow );

#ifdef TARGET_D3D
	D3DDevice	*d3ddevp = _rdevicep->GetD3DDevice();
	d3ddevp->SetVertexShaderConstantF( _VSP_U_diffuse_col, diffuse_col._v, 1 );
	d3ddevp->SetPixelShaderConstantF( _FSP_U_specular_col_pow, spec._v, 1 );
	d3ddevp->SetVertexShaderConstantF( _VSP_U_emissive_col, emissive_col._v, 1 );

#elif defined(TARGET_OPENGL)
	cgGLSetParameter4fv( _VSP_U_diffuse_col,	(const float *)diffuse_col._v );
	cgGLSetParameter4fv( _FSP_U_specular_col_pow,(const float *)spec._v );
	cgGLSetParameter4fv( _VSP_U_emissive_col,(const float *)emissive_col._v );

#endif
}

//==================================================================
void RendShaderManager::Std::SetDiffuseTexture( TextureBase *texturep )
{
#if defined(TARGET_OPENGL)
	if ( texturep )
	{
//		glBindTexture( GL_TEXTURE_2D, texturep->_tex_ogl_id );
		cgGLSetTextureParameter( _cur_FSP_U_color_texmap, texturep->_tex_ogl_id );
		cgGLEnableTextureParameter( _cur_FSP_U_color_texmap );
	}
	else
	{
		cgGLDisableTextureParameter( _cur_FSP_U_color_texmap );
	}
#endif
}

//==================================================================
void RendShaderManager::Std::SetFogColor( const Vector3 &fog_col )
{
#ifdef TARGET_D3D
	_rdevicep->GetD3DDevice()->SetPixelShaderConstantF( _FSP_U_fog_col, Vector4(fog_col,0)._v, 1 );
#elif defined(TARGET_OPENGL)
	cgGLSetParameter4fv( _FSP_U_fog_col, Vector4(fog_col,0)._v );
#endif
}

//==================================================================
void RendShaderManager::Std::SetFogRange( float fog_start_depth, float fog_end_depth )
{
	Vector4	fog_range(	0,
						fog_end_depth,
						1.00f / (fog_end_depth - fog_start_depth),
						0 );

#ifdef TARGET_D3D
	_rdevicep->GetD3DDevice()->SetVertexShaderConstantF( _VSP_U_fog_range, (const float *)fog_range._v, 1 );
#elif defined(TARGET_OPENGL)
	cgGLSetParameter4fv( _VSP_U_fog_range, (const float *)fog_range._v );
#endif
}

//==================================================================
void RendShaderManager::Std::SetParticleScale( float part_scale )
{
#ifdef TARGET_D3D
	_rdevicep->GetD3DDevice()->SetVertexShaderConstantF( _VSP_U_PART_SIZE, Vector4(part_scale,0,0,0)._v, 1 );
#elif defined(TARGET_OPENGL)
#endif

//	TouchUniformParam();
}

//==================================================================
void RendShaderManager::SelectVertexShader( RendShader *shaderp )
{
	if ( _cur_vtx_shaderp != shaderp )
	{
		_cur_vtx_shaderp = shaderp;
		cgGLBindProgram( shaderp->_program );
	}
}

//==================================================================
void RendShaderManager::SelectPixelShader( RendShader *shaderp )
{
	if ( _cur_pix_shaderp != shaderp )
	{
		_cur_pix_shaderp = shaderp;
		cgGLBindProgram( shaderp->_program );
	}
}

//==================================================================
void RendShaderManager::SetTexture( RendShader::Param tex_param, TextureBase *texturep )
{
#if defined(TARGET_OPENGL)
	if ( texturep )
	{
//		glBindTexture( GL_TEXTURE_2D, texturep->_tex_ogl_id );
		cgGLSetTextureParameter( tex_param, texturep->_tex_ogl_id );
		cgGLEnableTextureParameter( tex_param );
	}
	else
	{
		cgGLDisableTextureParameter( tex_param );
	}
#endif
}

//==================================================================
void RendShaderManager::SelectVertexStream(	const void *stream_posp,
											const void *stream_texp,
											const void *stream_colp,
											const void *stream_norp,
											int stride )
{
	glVertexPointer( 3, GL_FLOAT, stride, stream_posp );
	glEnableClientState( GL_VERTEX_ARRAY );

	if ( stream_texp )
	{
		glTexCoordPointer( 2, GL_FLOAT, stride, stream_texp );
		glEnableClientState( GL_TEXTURE_COORD_ARRAY );
	}
	else
		glDisableClientState( GL_TEXTURE_COORD_ARRAY );

	if ( stream_colp )
	{
		glColorPointer( 4, GL_UNSIGNED_BYTE, stride, stream_colp );
		glEnableClientState( GL_COLOR_ARRAY );
	}
	else
		glDisableClientState( GL_COLOR_ARRAY );

	if ( stream_norp )
	{
		glNormalPointer( GL_FLOAT, stride, stream_norp );
		glEnableClientState( GL_NORMAL_ARRAY );
	}
	else
		glDisableClientState( GL_NORMAL_ARRAY );
}

//==================================================================
void RendShaderManager::Std::SelectShader( bool has_vtex, bool has_vcolor, bool has_vnorm )
{
	int	tex = has_vtex		? 1 : 0;
	int	col = has_vcolor	? 1 : 0;
	int	nor = has_vnorm		? 1 : 0;

	_managerp->SelectVertexShader( _std_vs_shaderp[tex][col][nor] );
	
	_managerp->SelectPixelShader( _std_ps_shaderp[tex][nor] );
	_cur_FSP_U_color_texmap = _FSP_U_color_texmap[0];//nor];
}

//==================================================================
char *RendShaderManager::Std::MakeStdVSName_s( char out_name[128], int tex, int col, int nor )
{
	sprintf_s( out_name, 128, "Std_P1_T%i_C%i_N%i_VS", tex, col, nor );
	return out_name;
}

//==================================================================
char *RendShaderManager::Std::MakeStdPSName_s( char out_name[128], int tex, int nor )
{
	sprintf_s( out_name, 128, "Std_T%i_N%i_PS", tex, nor );
	return out_name;
}

//==================================================================
//--------------------------------------------------------------------------------------
// Name: GaussianDistribution()
// Desc: Computes a two-parameter (x,y) Gaussian distribution using the given
//       standard deviation (rho)
//--------------------------------------------------------------------------------------
inline float gaussianDistribution( float x, float y, float rho )
{
	return expf( -(x*x + y*y)/(2*rho*rho) ) / sqrtf( 2*M_PI*rho*rho );
}

//==================================================================
void RendShaderManager::MakeBloomParams_s(	int dwTextureWidth, int dwTextureHeight, 
										float fAngle, Vector4 *pvTexCoordOffsets,
										Vector4 *pvColorWeights, float fDeviation,
										float fMultiplier )
{
	float tu = cosf(fAngle) / (float)dwTextureWidth;
	float tv = sinf(fAngle) / (float)dwTextureHeight;

	// Fill the center texel
	float fWeight = fMultiplier * gaussianDistribution( 0, 0, fDeviation );
	pvColorWeights[0]    = Vector4( fWeight, fWeight, fWeight, 1.0f );
	pvTexCoordOffsets[0] = Vector4( 0.0f, 0.0f, 0.0f, 0.0f );

	// Fill the first half
	for( int i=1; i<8; i++ )
	{
		// Get the Gaussian intensity for this offset
		fWeight = fMultiplier * gaussianDistribution( (float)i, 0, fDeviation );
		pvColorWeights[i]    = Vector4( fWeight, fWeight, fWeight, 1.0f );
		pvTexCoordOffsets[i] = Vector4( i * tu, i * tv, 0.0f, 0.0f );
	}

	// Mirror to the second half
	for( int i=8; i<15; i++ )
	{
		pvColorWeights[i]    =  pvColorWeights[i-7];
		pvTexCoordOffsets[i] = -pvTexCoordOffsets[i-7];
	}
}

//==================================================================
void RendShaderManager::BeginRender()
{
	glDisable( GL_LIGHTING );
	glColor4f( 1, 1, 1, 1 );
	cgGLEnableProfile( _vs_profile );
	cgGLEnableProfile( _ps_profile );
	_cur_vtx_shaderp = NULL;
	_cur_pix_shaderp = NULL;

	//	glMatrixMode( GL_PROJECTION );
	//	glLoadIdentity();
	//	glMatrixMode( GL_MODELVIEW );
}

//==================================================================
void RendShaderManager::EndRender()
{
	cgGLDisableProfile( _vs_profile );
	cgGLDisableProfile( _ps_profile );
	_cur_vtx_shaderp = NULL;
	_cur_pix_shaderp = NULL;
}

//==================================================================
void RendShaderManager::ResetState()
{
	_cur_vtx_shaderp = NULL;
	_cur_pix_shaderp = NULL;
}

//==================================================================
/// RendShader
//==================================================================
RendShader::RendShader( RendShaderManager *managerp ) :
	_managerp(managerp),
	_program(0)
{
}

//==================================================================
RendShader::~RendShader()
{
	if ( _program )
		cgDestroyProgram( _program );
}

//==================================================================
void RendShader::CreatePixelProgram( const char *sourcep, const char *entrypointp/*=NULL */ )
{
#if defined(TARGET_OPENGL)
	_program = cgCreateProgram( _managerp->_context, CG_SOURCE,
								sourcep,
								_managerp->_ps_profile,
								entrypointp,
								NULL );

	cgGLLoadProgram( _program );
#else
	#error "Missing target"
#endif
}

//==================================================================
void RendShader::CreateVertexProgram( const char *sourcep, const char *entrypointp/*=NULL */ )
{
#if defined(TARGET_OPENGL)
	_program = cgCreateProgram( _managerp->_context, CG_SOURCE,
								sourcep,
								_managerp->_vs_profile,
								entrypointp,
								NULL );

	cgGLLoadProgram( _program );
#else
	#error "Missing target"
#endif
}

//==================================================================
int RendShader::findParamIdxByName( const char *param_namep )
{
	for (int i=0; i < _params_list.size(); ++i)
	{
		if NOT( _stricmp( param_namep, _params_list[i]._param_name ) )
		{
			return i;
		}
	}

	return -1;
}

//==================================================================
RendShader::Param RendShader::AddParam( const char *param_namep )
{
#if defined(TARGET_OPENGL)
	CGparameter		base_param = cgGetNamedParameter( _program, param_namep );

	ParamInfo	pinfo;

	pinfo._is_original = true;
	pinfo._prog_param = base_param;
	strcpy_s( pinfo._param_name, param_namep );

	_params_list.push_back( pinfo );

	return base_param;//_params_list.len()-1;
#else

	#error "Missing target"

#endif
}

//==================================================================
RendShader::Param RendShader::AddParamShared( const char *param_namep )
{
#if defined(TARGET_OPENGL)
	CGparameter		base_param = cgGetNamedParameter( _program, param_namep );
	CGtype			par_type = cgGetParameterType( base_param );
	CGparameter		param = cgCreateParameter( _managerp->_context, par_type );

	cgConnectParameter( param, base_param );

	ParamInfo	pinfo;

	pinfo._is_original = true;
	pinfo._prog_param = param;
	strcpy_s( pinfo._param_name, param_namep );

	_params_list.push_back( pinfo );
#else
	#error "Missing target"
#endif

	return param;//_params_list.len()-1;
}

//==================================================================
RendShader::Param RendShader::CloneParam( const char *param_namep, RendShader *from_shaderp )
{
#if defined(TARGET_OPENGL)
	int	from_idx = from_shaderp->findParamIdxByName( param_namep );

	if NOT( PTRAP_FALSE( from_idx != -1 ) )
		return (RendShader::Param)0;

	CGparameter		local_param = cgGetNamedParameter( _program, param_namep );
	cgConnectParameter( from_shaderp->_params_list[from_idx]._prog_param, local_param );

	return from_shaderp->_params_list[from_idx]._prog_param;
#else
	#error "Missing target"
#endif

	return (RendShader::Param)0;
}

//==================================================================
RendShader::Param RendShader::GetParamByName( const char *param_namep )
{
	int	idx = findParamIdxByName( param_namep );

	if ( idx >= 0 )
		return _params_list[ idx ]._prog_param;
	else
	{
		PASSERT( 0 );
		return 0;
	}
}
//==================================================================
void RendShaderManager::Std::SelectPntSprtShader( bool has_vcolor, float max_size )
{
	// $$$
}

//==================================================================
void RendShaderManager::Std::SelectStdVDef( int tex, int col, int nor )
{
}

//==================================================================
void RendShaderManager::SelectVertexBuffer( class RendVertexBuffer *vbuffp )
{
}

//==================================================================
void RendShaderManager::SelectDownsample4x4ClampShader( u_int src_wd, u_int src_he )
{
}

//==================================================================
void RendShaderManager::SelectBloomShader( const PMath::Vector4 *samp_offsp,
												 const PMath::Vector4 *samp_weightsp,
												 float bright_threshold )
{
}

//==================================================================
void RendShaderManager::SelectPlainTextureShader()
{
}

//==================================================================
void RendShaderManager::SelectHDRFinalPassShader( const PMath::Vector4 &bloom_scale )
{
}
